package connection;

import form.MainFrame;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import p2pExceptions.BufferNotReadyException;

/**
 *
 * @author hz
 */
public class ConnectionManager extends Thread {

    public ConnectionManager() {
        connected = false;
        ip = "";
        socket = null;
        port = 5678;
    }

    public boolean isConnected() {
        return connected;
    }

    public void setAddress(String address) {
        ip = address;
    }

    public String getAddress() {
        return ip;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getPort() {
        return port;
    }

    public boolean connect(String address, String port) throws IOException {
        try {
            ip = address;
            try {
                Integer.parseInt(port);
            } catch (NumberFormatException ex) {
                //System.out.println("Invalid value for port: " + port);
                Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, "Invalid value for port: " + port, ex);
                throw ex;
            }
            System.out.println("test3"); //never get here?!?
            
            return connect();
        } catch (IOException ex) {
        	Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        } 
    }

	@Override
	public void run() {
		while (connected){
			try {
				if (connected && reader.ready()){
					_fireStreamEvent();
				}
			} catch (IOException e) {}
		}
	}
     
    public boolean connect() throws IOException {
        try {
            Logger.getLogger(HostManager.class.getName()).log(Level.INFO, "Connecting..");
            socket = new Socket(ip, port);
            Logger.getLogger(HostManager.class.getName()).log(Level.INFO, "Connected...");
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            writer = new PrintWriter(socket.getOutputStream(), true);
            writer.println(MainFrame.currentPlayer.toString());

            String ack = reader.readLine();

            if (ack.equals("Play"))
                connected = true;
            else if(ack.equals("Decline"))//Needs Declined
                connected = false;
            else loadFile(ack); //Needs to parse ack to get hash and filname

        } catch (SocketException ex) {
            Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, "Socket error..", ex);
            throw ex;
        }
        catch (UnknownHostException ex) {// Lets punt this exception to the caller.
            throw ex;
        } catch (IOException ex) {
            Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
        return connected;
    }

    //this code is common between host and client!!!
    public String receiveData() throws IOException, BufferNotReadyException{
        try {
            if(reader.ready()){
            	readBuffer=reader.readLine();
    			if (!(oldBuffer.equals(readBuffer))){ //something new
                	oldBuffer=readBuffer;
                	return oldBuffer;
    			}//end new data    
            }//end reader ready
            else {
            	System.out.println("reader is not ready in receive");
            }
        } catch (IOException ex) {
            Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
		return null;
    }
    
 
    //unused???
    public boolean confirmMove() throws IOException, BufferNotReadyException{
        movesConfirmed=false;
        try {
            if(reader.ready()){
            	readBuffer=reader.readLine();
        		System.out.println("readbuffer = " + readBuffer);//troubleshooter

	                 if (readBuffer.charAt(0) == '1') {
                		System.out.println("received move "+ readBuffer.substring(2,6));//troubleshooter
                    	movesConfirmed = true;
	                 } else{
	                	System.out.println("huh?");
	                    System.out.println(readBuffer);
	                 }
            }//end reader ready
            else System.out.println("reader dead");//troubleshooter

        } catch (IOException ex) {
            Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
		return false;
    }


    private void loadFile(String fileInfo){
        fileNam = fileInfo.substring(fileInfo.indexOf("[file=") + "[file=".length(),fileInfo.indexOf(";", fileInfo.indexOf("[file")+1));
        oppHash = fileInfo.substring(fileInfo.indexOf(";hash=")+ ";hash=".length(), fileInfo.indexOf("]", fileInfo.indexOf(";hash")+1));
        System.out.println("Client recieved file: "+fileNam+" file and Hash:"+oppHash+" From HOST");
        File file = new File(fileNam+".chs");
        if(file.exists()){
            try{
            fstream = new FileInputStream(file);
            scanner = new Scanner(fstream);
                while (scanner.hasNextLine()) {
                    if(myHash.equals("BLACK") ){connColor = Color.BLACK;}
                    if(myHash.equals("WHITE")){connColor = Color.WHITE;}
                    myHash = scanner.nextLine();
                     }
            fstream.close();
            scanner.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
                if(myHash.equals(oppHash)){
                isLoad = true;
                connected = true;
                System.out.println("Files matches with the name and hash value");
                writer.println("LoadGame");               
                }
                if(!myHash.equals(oppHash)){
                connected = true;
                myHash = null;
                isLoad = false;
                System.out.println("The hash value does not match for both file");
                }
        }
        else if(!file.exists()){
                connected = true;
                myHash = null;
                isLoad = false;
                System.out.println("Given "+fileNam+" does not exist for ConnMan");
                }
    }

    public String getHash(){
        return myHash;
    }

    public boolean isLoad(){
        return isLoad;
    }

    public PrintWriter getWriter(){
        return writer;
    }

    public BufferedReader getReader(){
        return reader;
    }

    public void closeReader() throws IOException{
        try {
            reader.close();
        } catch (IOException ex) {
            Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
    }

    public void sendData(String data) {
    	movesConfirmed=false;
    	System.out.println("Client sending..." + data);
        writer.println(data);
    }

	public void disconnect() throws IOException {
        if (socket != null || socket.isClosed()) {
            try {
                socket.close();
                reader.close();
                writer.close();
            } catch (IOException ex) {
                Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
                throw ex;
            }
        }
        connected = false;
        interrupt();
    }
    
    public boolean getMovesConfirmed() {
        return movesConfirmed;
    }


    public Color getConnColor(){
        return connColor;
    }

    private String readBuffer;
    private String oldBuffer = "";
    private BufferedReader reader;
    private PrintWriter writer;
    private boolean connected;
    private String ip;
    private int port;
    private Socket socket;
    private boolean movesConfirmed = false;
    private String fileNam = null;
    private String oppHash, myHash = "null";
    private boolean isLoad = false;
    private FileInputStream fstream = null;
    private Scanner scanner = null;
    private Color connColor; //If files matched
    
    

    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^listener stuff^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	private ArrayList _listeners = new ArrayList();

	public synchronized void addStreamListener(StreamListener l) {
        _listeners.add(l);
    }
    
    public synchronized void removeStreamListener(StreamListener l) {
        _listeners.remove(l);
    }
     
	private synchronized void _fireStreamEvent() {
        StreamEvent stream = new StreamEvent(this);
		Iterator listeners = _listeners.iterator();
        while(listeners.hasNext()) {
            ((StreamListener) listeners.next()).streamReceived(stream);
        }
        
    }
    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^listener stuff^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    
    
}
